home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 2848 / 2848.xpi / chrome / passwordexporter.jar / content / pwdex-loginmanager.js < prev    next >
Text File  |  2009-08-04  |  35KB  |  673 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Password Exporter
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  *    Justin Scott <fligtar@gmail.com>.
  18.  *
  19.  * Portions created by the Initial Developer are Copyright (C) 2006
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s): (none)
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. /**
  39.  * Password Exporter - Login Manager support
  40.  * This file is for use with the new login manager in Firefox 3
  41.  */
  42.  
  43. var passwordExporterLoginMgr = {
  44.     export: {
  45.         currentExport: '', // CSV or XML string of current export
  46.         count: 0, // count of exported logins
  47.         errorCount: 0, // count of failed logins
  48.         failed: '', // failed hosts
  49.         
  50.         // starts export of saved passwords to XML/CSV file
  51.         start: function() {
  52.             passwordExporter.debug('Starting Export...');
  53.             
  54.             // Check if user has accepted agreement
  55.             passwordExporter.checkAgreement();
  56.             
  57.             if (passwordExporter.accepted == true) {
  58.                 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
  59.                 var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
  60.                 
  61.                 // Prompt user to select where to save the export
  62.                 fp.init(window, passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-title'), fp.modeSave);
  63.                 fp.defaultString = 'password-export-' + passwordExporter.getDateString();
  64.                 fp.defaultExtension = '.xml';
  65.                 fp.appendFilter(passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-save-xml'), '*.xml');
  66.                 fp.appendFilter(passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-save-csv'), '*.csv');
  67.                 
  68.                 // If cancelled, return
  69.                 if (fp.show() == fp.returnCancel)
  70.                     return;
  71.                 
  72.                 // Remove file if it exists
  73.                 if (fp.file.exists())
  74.                     fp.file.remove(true);
  75.                 
  76.                 fp.file.create(fp.file.NORMAL_FILE_TYPE, 0666);
  77.                 stream.init(fp.file, 0x02, 0x200, null);
  78.                 
  79.                 // Whether to encrypt the passwords
  80.                 var encrypt = document.getElementById('pwdex-encrypt').checked;
  81.                 
  82.                 // do export
  83.                 if (fp.filterIndex == 0)
  84.                     var content = this.export('xml', encrypt);
  85.                 else if (fp.filterIndex == 1)
  86.                     var content = this.export('csv', encrypt);
  87.                 
  88.                 stream.write(content, content.length);
  89.                 stream.close();
  90.                 
  91.                 passwordExporter.debug('Export of ' + this.count + ' entries completed with ' + this.errorCount + ' errors.');
  92.                 
  93.                 if (this.errorCount == 0)
  94.                     alert(passwordExporter.bundle.formatStringFromName('passwordexporter.alert-passwords-exported', [this.count], 1));
  95.                 else {
  96.                     var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  97.                     
  98.                     var flags = promptService.BUTTON_TITLE_OK * promptService.BUTTON_POS_0 +
  99.                     promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1;
  100.                     
  101.                     var response = promptService.confirmEx(window, passwordExporter.bundle.GetStringFromName('passwordexporter.name'),
  102.                                     passwordExporter.bundle.formatStringFromName('passwordexporter.alert-passwords-exported', [this.count], 1) + "\n\n" +
  103.                                     passwordExporter.bundle.formatStringFromName('passwordexporter.alert-passwords-failed', [this.errorCount], 1), flags,
  104.                                     null, passwordExporter.bundle.GetStringFromName('passwordexporter.show-details'), null, null, {});
  105.                     
  106.                     if (response == 1)
  107.                         window.openDialog("chrome://passwordexporter/content/pwdex-details-export.xul", "","chrome,resizable,centerscreen,close=no,modal");
  108.                 }
  109.             }
  110.         },
  111.     
  112.         // Generates XML/CSV from Login Manager entries
  113.         export: function(type, encrypt) {
  114.             passwordExporter.debug('Generating ' + type + ' entries...');
  115.             if (type == 'xml') {
  116.                 this.currentExport = '<xml>' + passwordExporter.linebreak;
  117.                 this.currentExport += '<entries ext="Password Exporter" extxmlversion="1.1" type="saved" encrypt="' + encrypt + '">' + passwordExporter.linebreak;
  118.             }
  119.             else if (type == 'csv') {
  120.                 this.currentExport = '# Generated by Password Exporter; Export format 1.1; Encrypted: ' + encrypt + passwordExporter.linebreak;
  121.                 this.currentExport += '"hostname","username","password","formSubmitURL","httpRealm","usernameField","passwordField"' + passwordExporter.linebreak;
  122.             }
  123.             
  124.             this.count = 0;
  125.             this.errorCount = 0;
  126.             passwordExporter.failed = '';
  127.             
  128.             var loginManager = CC_loginManager.getService(Components.interfaces.nsILoginManager);
  129.             var logins = loginManager.getAllLogins({});
  130.             
  131.             for (var i = 0; i < logins.length; i++) {
  132.                 if (type == 'xml') {
  133.                     this.entryToXML(logins[i].hostname, logins[i].formSubmitURL, logins[i].httpRealm, logins[i].username,
  134.                                logins[i].usernameField, logins[i].password, logins[i].passwordField, encrypt);
  135.                 }
  136.                 else if (type == 'csv') {
  137.                     this.entryToCSV(logins[i].hostname, logins[i].formSubmitURL, logins[i].httpRealm, logins[i].username,
  138.                                logins[i].usernameField, logins[i].password, logins[i].passwordField, encrypt);
  139.                 }
  140.             }
  141.             
  142.             if (type == 'xml') {
  143.                 this.currentExport += '</entries>' + passwordExporter.linebreak + '</xml>';
  144.             }
  145.             
  146.             return this.currentExport;
  147.         },
  148.         
  149.         // Records an nsILoginInfo entry to XML
  150.         entryToXML: function(hostname, formSubmitURL, httpRealm, username, usernameField,
  151.                             password, passwordField, encrypt) {
  152.             if (encrypt) {
  153.                 username = btoa(username);
  154.                 password = btoa(password);
  155.             }
  156.             
  157.             try {
  158.                 var xml  = '<entry';
  159.                 xml += ' host="' + this.escapeQuote(hostname) + '"';
  160.                 xml += ' user="' + this.escapeQuote(username) + '"';
  161.                 xml += ' password="' + this.escapeQuote(password) + '"';
  162.                 
  163.                 xml += ' formSubmitURL="' + (formSubmitURL ? this.escapeQuote(formSubmitURL) : '') + '"';
  164.                 xml += ' httpRealm="' + (httpRealm ? this.escapeQuote(httpRealm) : '') + '"';
  165.                 xml += ' userFieldName="' + (usernameField ? this.escapeQuote(usernameField) : '') + '"';
  166.                 xml += ' passFieldName="' + (passwordField ? this.escapeQuote(passwordField) : '') + '"';
  167.                 
  168.                 xml += '/>' + passwordExporter.linebreak;
  169.                 
  170.                 this.currentExport += xml;
  171.                 this.count++;
  172.             } catch (e) {
  173.                 this.errorCount++;
  174.                 try {
  175.                     this.failed += hostname + passwordExporter.linebreak;
  176.                 } catch (e) { }
  177.             }
  178.         },
  179.         
  180.         // Records an nsILoginInfo entry to CSV
  181.         entryToCSV: function(hostname, formSubmitURL, httpRealm, username, usernameField,
  182.                             password, passwordField, encrypt) {
  183.             if (encrypt) {
  184.                 username = btoa(username);
  185.                 password = btoa(password);
  186.             }
  187.             
  188.             try {
  189.                 var csv = '"' + this.escapeQuote(hostname) + '",';
  190.                 csv += '"' + this.escapeQuote(username) + '",';
  191.                 csv += '"' + this.escapeQuote(password) + '",';
  192.                 
  193.                 csv += '"' + (formSubmitURL ? this.escapeQuote(formSubmitURL) : '') + '",';
  194.                 csv += '"' + (httpRealm ? this.escapeQuote(httpRealm) : '') + '",';
  195.                 csv += '"' + (usernameField ? this.escapeQuote(usernameField) : '') + '",';
  196.                 csv += '"' + (passwordField ? this.escapeQuote(passwordField) : '')+ '"';
  197.                 
  198.                 csv += passwordExporter.linebreak;
  199.                 
  200.                 this.currentExport += csv;
  201.                 this.count++;
  202.             } catch (e) {
  203.                 this.errorCount++;
  204.                 try {
  205.                     this.failed += hostname + passwordExporter.linebreak;
  206.                 } catch (e) { }
  207.             }
  208.         },
  209.         
  210.         // escapes only quotes and ampersands so that it will parse correctly in XML
  211.         escapeQuote: function(string) {
  212.             string = string.replace(/%/gi, '%25');
  213.             string = string.replace(/</gi, '%3C');
  214.             string = string.replace(/>/gi, '%3E');
  215.             string = string.replace(/"/gi, '%22');
  216.             string = string.replace(/&/gi, '%26');
  217.             
  218.             return string;
  219.         },
  220.         
  221.         // populate details textbox with failed entries
  222.         populateFailed: function(textbox) {
  223.             textbox.value = this.failed;
  224.         },
  225.         
  226.         disabled: {
  227.             // starts export of login disabled sites that never saved passwords
  228.             start: function() {
  229.                 passwordExporter.debug('Starting Disabled Hosts Export...');
  230.                 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
  231.                 var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
  232.                 
  233.                 fp.init(window, passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-title'), fp.modeSave);
  234.                 fp.defaultString = 'disabled-export-' + passwordExporter.getDateString();
  235.                 fp.defaultExtension = '.xml';
  236.                 fp.appendFilters(fp.filterXML);
  237.                 
  238.                 // If cancelled, return
  239.                 if (fp.show() == fp.returnCancel)
  240.                     return;
  241.                 
  242.                 if (fp.file.exists())
  243.                     fp.file.remove(true);
  244.                 
  245.                 fp.file.create(fp.file.NORMAL_FILE_TYPE, 0666);
  246.                 stream.init(fp.file, 0x02, 0x200, null);
  247.                 
  248.                 var xml = this.export();
  249.                 
  250.                 stream.write(xml, xml.length);
  251.                 stream.close();
  252.                 
  253.                 passwordExporter.debug('Disabled hosts export complete.');
  254.                 
  255.                 alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-rejected-exported'));
  256.             },
  257.             
  258.             // Gets disabled hosts from Login Manager
  259.             export: function() {
  260.                 var xml = '<xml>' + passwordExporter.linebreak;
  261.                 xml += '<entries ext="Password Exporter" extxmlversion="1.0.2" type="rejected">' + passwordExporter.linebreak;
  262.                 
  263.                 var loginManager = CC_loginManager.getService(Components.interfaces.nsILoginManager);
  264.                 var disabledHosts = loginManager.getAllDisabledHosts({});
  265.                 
  266.                 for (var i = 0; i < disabledHosts.length; i++) {
  267.                     xml += '<entry host="' + disabledHosts[i] + '"/>' + passwordExporter.linebreak;
  268.                 }
  269.                 
  270.                 xml += '</entries>' + passwordExporter.linebreak + '</xml>';
  271.                 
  272.                 return xml;
  273.             }
  274.         }
  275.     
  276.     },
  277.     
  278.     import: {
  279.         totalCount: 0, // total number of logins
  280.         currentCount: 0, // number of logins currently imported
  281.         cancelled: false, // whether the operation was cancelled
  282.         failed: '', // list of failed hosts
  283.         
  284.         // Starts the import of logins from a CSV or XML file
  285.         start: function() {
  286.             passwordExporter.debug('Starting Import...');
  287.             
  288.             var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
  289.             var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
  290.             var streamIO = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
  291.             var input, inputArray, importType, doc, header, name, type, version, encrypt;
  292.             
  293.             fp.init(window, passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-title'), fp.modeOpen);
  294.             fp.appendFilter(passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-open-xmlcsv'), '*.xml; *.csv; *');
  295.             
  296.             // If cancelled, return
  297.             if (fp.show() == fp.returnCancel)
  298.                 return;
  299.             
  300.             stream.init(fp.file, 0x01, 0444, null);
  301.             streamIO.init(stream);
  302.             input = streamIO.read(stream.available());
  303.             streamIO.close();
  304.             stream.close();
  305.             
  306.             var parser = new DOMParser();
  307.             
  308.             // If CSV format, parse for header info
  309.             if (fp.file.path.indexOf('.csv') != -1) {
  310.                 // Starting in 1.1, header is in a "comment" at the top
  311.                 var header = /# Generated by (.+); Export format (.{3,6}); Encrypted: (true|false)/i.exec(input);
  312.                 if (!header) {
  313.                     // Previously, the header was in CSV form in the first line
  314.                     header = /(.+?),(.{3,6}),(true|false)/i.exec(input);
  315.                 }
  316.                 if (!header) {
  317.                     // If we still can't read header, there's a problem with the file
  318.                     alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-cannot-import'));
  319.                     return;
  320.                 }
  321.                 var properties = {'extension': header[1],
  322.                                   'importtype': 'saved',
  323.                                   'importversion': header[2],
  324.                                   'encrypt': header[3]};
  325.                 this.import('csv', properties, input);
  326.             }
  327.             // If XML format, parse for header info
  328.             else {
  329.                 var doc = parser.parseFromString(input, "text/xml");
  330.                 var header = doc.documentElement.getElementsByTagName('entries')[0];
  331.                 
  332.                 if (doc.documentElement.nodeName == 'parsererror') {
  333.                     alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-xml-error'));
  334.                     return;
  335.                 }
  336.                 
  337.                 var properties = {'extension': header.getAttribute('ext'),
  338.                                   'importtype': header.getAttribute('type'),
  339.                                   'importversion': header.getAttribute('extxmlversion'),
  340.                                   'encrypt': header.getAttribute('encrypt')};
  341.                 var entries = doc.documentElement.getElementsByTagName('entry');
  342.                 this.import('xml', properties, entries);
  343.             }
  344.         },
  345.         
  346.         // Validates import file and parses it
  347.         import: function (type, properties, entries) {
  348.             passwordExporter.debug(type + ' file read...');
  349.             
  350.             // Make sure this is a Password Exporter export
  351.             if (properties.extension != 'Password Exporter') {
  352.                 alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-cannot-import'));
  353.                 return;
  354.             }
  355.             
  356.             // Make sure this is a saved passwords file, as opposed to disabled hosts
  357.             if (properties.importtype != 'saved') {
  358.                 alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-wrong-file-reject'));
  359.                 return;
  360.             }
  361.             
  362.             // Make sure this was exported from a version supported (not a future version)
  363.             if (properties.importversion in {'1.0.2':'', '1.0.4':'', '1.1':''}) {
  364.                 // Import
  365.                 var logins = [];
  366.                 this.totalCount = 0;
  367.                 this.currentCount = 0;
  368.                 
  369.                 passwordExporter.disableAllButtons();
  370.                 document.getElementById('pwdex-import-finished').hidden = true;
  371.                 document.getElementById('pwdex-import-view-details').hidden = true;
  372.                 document.getElementById('pwdex-import-complete').hidden = true;
  373.                 document.getElementById('pwdex-import-cancelled').hidden = true;
  374.                 document.getElementById('pwdex-import-status').value = '';
  375.                 document.getElementById('pwdex-import-underway').hidden = false;
  376.                 document.getElementById('pwdex-import-cancel').hidden = false;
  377.                 
  378.                 var loginManager = CC_loginManager.getService(Components.interfaces.nsILoginManager);
  379.                 var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
  380.                                          Components.interfaces.nsILoginInfo, "init");
  381.                 if (type == 'xml') {
  382.                     this.totalCount = entries.length;
  383.                     
  384.                     for (var i = 0; i < entries.length; i++) {
  385.                         var loginInfo = new nsLoginInfo(
  386.                                                 (entries[i].getAttribute('host') == null ? null : unescape(entries[i].getAttribute('host'))),
  387.                                                 (entries[i].getAttribute('formSubmitURL') == null ? "" : unescape(entries[i].getAttribute('formSubmitURL'))),
  388.                                                 ((entries[i].getAttribute('httpRealm') == null || entries[i].getAttribute('httpRealm') == "") ? null : unescape(entries[i].getAttribute('httpRealm'))),
  389.                                                 unescape(entries[i].getAttribute('user')),
  390.                                                 unescape(entries[i].getAttribute('password')),
  391.                                                 (entries[i].getAttribute('userFieldName') == null ? null : unescape(entries[i].getAttribute('userFieldName'))),
  392.                                                 (entries[i].getAttribute('passFieldName') == null ? null : unescape(entries[i].getAttribute('passFieldName')))
  393.                                             );
  394.                         
  395.                         var formattedLogins = this.getFormattedLogin(properties, loginInfo);
  396.                         for each (var login in formattedLogins) {
  397.                             logins.push(login);
  398.                         }
  399.                     }
  400.                 }
  401.                 else if (type == 'csv') {
  402.                     if (/\r\n/i.test(entries))
  403.                         var entryArray = entries.split("\r\n");
  404.                     else if (/\r/i.test(entries))
  405.                         var entryArray = entries.split("\r");
  406.                     else
  407.                         var entryArray = entries.split("\n");
  408.                     
  409.                     // Prior to version 1.1, we only had one line of header
  410.                     // After 1.1, there was a header comment and a labels line
  411.                     if (properties.importversion == '1.0.2' || properties.importversion == '1.0.4')
  412.                         var start = 1;
  413.                     else
  414.                         var start = 2;
  415.                     
  416.                     for (var i = start; i < (entryArray.length - 1); i++) {
  417.                         if (properties.importversion == '1.0.2' || properties.importversion == '1.0.4') {
  418.                             // Before version 1.1, csv didn't have quotes
  419.                             var fields = entryArray[i].split(',');
  420.                             
  421.                             var loginInfo = new nsLoginInfo(
  422.                                                     (fields[0] == '' ? null : unescape(fields[0])),
  423.                                                     "", // formSubmitURL
  424.                                                     null, // httpRealm
  425.                                                     unescape(fields[1]), // username
  426.                                                     unescape(fields[2]), // password
  427.                                                     (fields[3] == '' ? null : unescape(fields[3])), // usernameField
  428.                                                     (fields[4] == '' ? null : unescape(fields[4])) // passwordField
  429.                                                 );
  430.                         }
  431.                         else {
  432.                             // Version 1.1 CSV has quotes and 2 new fields
  433.                             var fields = entryArray[i].split('","');
  434.                             
  435.                             var loginInfo = new nsLoginInfo(
  436.                                                     (fields[0] == '"' ? null : unescape(fields[0].replace('"', ''))), // hostname
  437.                                                     (fields[3] == '' ? "" : unescape(fields[3])), // formSubmitURL
  438.                                                     (fields[4] == '' ? null : unescape(fields[4])), // httpRealm
  439.                                                     unescape(fields[1]), // username
  440.                                                     unescape(fields[2]), // password
  441.                                                     (fields[5] == '' ? null : unescape(fields[5])), // usernameField
  442.                                                     (fields[6] == '"' ? null : unescape(fields[6].replace('"', ''))) // passwordField
  443.                                                 );
  444.                         }
  445.                         
  446.                         var formattedLogins = this.getFormattedLogin(properties, loginInfo);
  447.                         for each (var login in formattedLogins) {
  448.                             logins.push(login);
  449.                         }
  450.                     }
  451.                 }
  452.                 
  453.                 this.insertEntries(logins);
  454.                 
  455.                 // because of window timers, we can't put post-insert steps here
  456.                 // they are now located in passwordExporterLoginMgr.import.finished()
  457.             }
  458.             else
  459.                 alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-wrong-version'));
  460.         },
  461.         
  462.         // Makes sure logins are formatted correctly for Firefox 3
  463.         getFormattedLogin: function(properties, loginInfo) {
  464.             passwordExporter.debug('pre-getFormattedLogin: [hostname: ' + loginInfo.hostname + ', httpRealm: ' + loginInfo.httpRealm + ', formSubmitURL: ' + loginInfo.formSubmitURL + ', usernameField: ' + loginInfo.usernameField + ', passwordField: ' + loginInfo.passwordField + ']');
  465.             
  466.             // in version 1.0.2, encryption was only for passwords... in 1.0.4 we encrypt usernames as well    
  467.             if (properties.encrypt == 'true') {
  468.                 loginInfo.password = atob(loginInfo.password);
  469.                 
  470.                 if (properties.importversion != '1.0.2')
  471.                     loginInfo.username = atob(loginInfo.username);
  472.             }
  473.             
  474.             // No null usernames or passwords
  475.             if (loginInfo.username == null)
  476.                 loginInfo.username = '';
  477.             if (loginInfo.password == null)
  478.                 loginInfo.password = '';
  479.                 
  480.             // If no httpRealm, check to see if it's in the hostname
  481.             if (!loginInfo.httpRealm) {
  482.                 var hostnameParts = /(.*) \((.*)\)/.exec(loginInfo.hostname);
  483.                 if (hostnameParts) {
  484.                     loginInfo.hostname = hostnameParts[1];
  485.                     loginInfo.httpRealm = hostnameParts[2];
  486.                 }
  487.             }
  488.             
  489.             // Convert to 2E (remove httpRealm from hostname, convert protocol logins, etc)
  490.             loginInfo = passwordExporterStorageLegacy._upgrade_entry_to_2E(loginInfo);
  491.             for each (var login in loginInfo) {
  492.                 if (login.httpRealm != null)
  493.                     login.formSubmitURL = null;
  494.                 
  495.                 passwordExporter.debug('post-getFormattedLogin: [hostname: ' + login.hostname + ', httpRealm: ' + login.httpRealm + ', formSubmitURL: ' + login.formSubmitURL + ', usernameField: ' + login.usernameField + ', passwordField: ' + login.passwordField + ']');
  496.             }
  497.             
  498.             return loginInfo;
  499.         },
  500.         
  501.         // Starts the generator to insert the logins
  502.         insertEntries: function(entries) {
  503.             this.totalCount = entries.length;
  504.             this.cancelled = false;
  505.             this.failed = '';
  506.             
  507.             this.insertGenerator = this.doInsert(entries);
  508.             window.setTimeout("passwordExporter.import.updateProgress()", 0);
  509.         },
  510.         
  511.         // Updates the progress bar and iterates the generator
  512.         updateProgress: function() {
  513.             var i = this.insertGenerator.next();
  514.             var percentage = Math.floor((this.currentCount / this.totalCount) * 100);
  515.             document.getElementById('pwdex-import-progress').value = percentage;
  516.             document.getElementById('pwdex-import-status').value = this.currentCount + '/' + this.totalCount;
  517.             
  518.             // If cancelled, don't add another timer
  519.             if (this.cancelled) {
  520.                 passwordExporter.import.finished();
  521.                 return;
  522.             }
  523.             5
  524.             // Add another timer if there are more logins
  525.             if (i < this.totalCount)
  526.                 window.setTimeout("passwordExporter.import.updateProgress()", 0);
  527.             else if (i == this.totalCount)
  528.                 passwordExporter.import.finished();
  529.         },
  530.         
  531.         // Insert the new login into Login Manager
  532.         doInsert: function(entries) {
  533.             var loginManager = CC_loginManager.getService(Components.interfaces.nsILoginManager);
  534.             var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
  535.                                          Components.interfaces.nsILoginInfo, "init");
  536.             var i = 0;
  537.             while (true) {
  538.                 yield i;
  539.                 passwordExporter.debug('Adding: [hostname: ' + entries[i].hostname + ', httpRealm: ' + entries[i].httpRealm + ', formSubmitURL: ' + entries[i].formSubmitURL + ', username: ' + entries[i].username + ', usernameField: ' + entries[i].usernameField + ', passwordField: ' + entries[i].passwordField + ']');
  540.                 
  541.                 // Fix for issue 39
  542.                 if (entries[i].httpRealm) {
  543.                     entries[i].formSubmitURL = null;
  544.                 }
  545.                 else {
  546.                     entries[i].httpRealm = null;
  547.                 }
  548.                 
  549.                 var loginInfo = new nsLoginInfo(entries[i].hostname, entries[i].formSubmitURL,
  550.                             entries[i].httpRealm, entries[i].username,
  551.                             entries[i].password, entries[i].usernameField,
  552.                             entries[i].passwordField);
  553.                 try {
  554.                     // Add the login
  555.                     loginManager.addLogin(loginInfo);
  556.                     
  557.                     this.currentCount++;
  558.                 }
  559.                 catch (e) {
  560.                     this.failed += entries[i].hostname + ' (' + e.message + ')' + passwordExporter.linebreak;
  561.                 }
  562.                 i++;
  563.             }
  564.         },
  565.         
  566.         // Cancel the import
  567.         cancel: function() {
  568.             this.cancelled = true;
  569.         },
  570.         
  571.         // Update UI to reflect import completion or cancellation
  572.         finished: function() {
  573.             if (document.getElementById('tabbox')) {
  574.                 // Refresh the listbox of passwords only if we are using the tab... the dialog version does not need to
  575.                 LoadSignons();
  576.             }
  577.             document.getElementById('pwdex-import-cancel').hidden = true;
  578.             document.getElementById('pwdex-import-finished').hidden = false;
  579.             
  580.             if (this.cancelled) {
  581.                 passwordExporter.debug('Import cancelled by user.');
  582.                 document.getElementById('pwdex-import-cancelled').hidden = false;
  583.             }
  584.             else {
  585.                 passwordExporter.debug('Import complete.');
  586.                 //alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-passwords-imported'));
  587.                 document.getElementById('pwdex-import-complete').hidden = false;
  588.             }
  589.             
  590.             // If there were failed entries, show a details link
  591.             if (this.failed != '')
  592.                 document.getElementById('pwdex-import-view-details').hidden = false;
  593.             
  594.             passwordExporter.enableAllButtons();
  595.         },
  596.         
  597.         // Open the import details window
  598.         showDetailsWindow: function() {
  599.             window.openDialog("chrome://passwordexporter/content/pwdex-details-import.xul", "","chrome,resizable,centerscreen,close=no,modal");
  600.         },
  601.         
  602.         // populate details textbox with failed entries
  603.         populateFailed: function(textbox) {
  604.             textbox.value = this.failed;
  605.         },
  606.         
  607.         disabled: {
  608.             // Starts import of disabled hosts from XML file
  609.             start: function() {
  610.                 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
  611.                 var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
  612.                 var streamIO = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
  613.                 var input;
  614.                 
  615.                 fp.init(window, passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-title'), fp.modeOpen);
  616.                 fp.appendFilter(passwordExporter.bundle.GetStringFromName('passwordexporter.filepicker-open-xml'), '*.xml; *');
  617.                 
  618.                 // If canceled, return
  619.                 if (fp.show() == fp.returnCancel)
  620.                     return;
  621.                 
  622.                 stream.init(fp.file, 0x01, 0444, null);
  623.                 streamIO.init(stream);
  624.                 input = streamIO.read(stream.available());
  625.                 streamIO.close();
  626.                 stream.close();
  627.                 
  628.                 var parser = new DOMParser();
  629.                 var doc = parser.parseFromString(input, "text/xml");
  630.                 
  631.                 var header = doc.documentElement.getElementsByTagName('entries')[0];
  632.                 
  633.                 // Return if parser error or no header
  634.                 if (doc.documentElement.nodeName == 'parsererror' || !header) {
  635.                     alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-xml-error'));
  636.                     return;
  637.                 }
  638.                 
  639.                 // Return if not Password Exporter
  640.                 if (header.getAttribute('ext') != 'Password Exporter') {
  641.                     alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-cannot-import'));
  642.                     return;
  643.                 }
  644.                 
  645.                 // Make sure it's a disabled hosts file
  646.                 if (header.getAttribute('type') != 'rejected') {
  647.                     alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-wrong-file-saved'));
  648.                     return;
  649.                 }
  650.                 
  651.                 var entries = doc.documentElement.getElementsByTagName('entry');
  652.                 this.import(entries);
  653.                 
  654.                 if (document.getElementById('tabbox')) {
  655.                     // Refresh the listbox of rejects only if we are using the tab... the dialog version does not need to
  656.                     LoadRejects();
  657.                 }
  658.                 
  659.                 alert(passwordExporter.bundle.GetStringFromName('passwordexporter.alert-rejected-imported'));
  660.             },
  661.             
  662.             // Import disabled hosts
  663.             import: function(entries) {
  664.                 var loginManager = CC_loginManager.getService(Components.interfaces.nsILoginManager);
  665.                 
  666.                 for (var i = 0; i < entries.length; i++) {
  667.                     loginManager.setLoginSavingEnabled(entries[i].getAttribute('host'), false);                    
  668.                 }
  669.             }
  670.         }
  671.     }
  672. };
  673.